﻿
#include "BinTree.h"
#include "NodeEntity.h"
#include "MenuWnd.h"
#include <stack>
using namespace std;

AFX_STATIC_DATA BOOL bCursorsInitialized = FALSE;
AFX_STATIC_DATA HCURSOR _afxCursors[10] = { 0, };

CBinTree::CBinTree()
{
	m_pRootNode = NULL;
	m_pSelectNode = NULL;
	
	if (!bCursorsInitialized)
	{
		// initialize the cursor array
		_afxCursors[0] = ::LoadCursorW(NULL, IDC_SIZENWSE);
		_afxCursors[1] = ::LoadCursorW(NULL, IDC_SIZENESW);
		_afxCursors[2] = _afxCursors[0];
		_afxCursors[3] = _afxCursors[1];
		_afxCursors[4] = ::LoadCursorW(NULL, IDC_CROSS); //::LoadCursorW(NULL, IDC_SIZENS);
		_afxCursors[5] = ::LoadCursorW(NULL, IDC_SIZEWE);
		_afxCursors[6] = _afxCursors[4];
		_afxCursors[7] = _afxCursors[5];
		_afxCursors[8] = ::LoadCursorW(NULL, IDC_SIZEALL);
		_afxCursors[9] = ::LoadCursorW(NULL, IDC_CROSS);

		bCursorsInitialized = TRUE;
	}
	m_ptOrigin = { 0, 0 };
	m_bSelect = FALSE;

	m_pLog = new CLog();
}

CBinTree::~CBinTree()
{
	save();

	// clean up the memory
	if (m_pRootNode)
		delete m_pRootNode;

	delete m_pLog;
}

CBinTree::CBinTree(CNode* pNode) : m_pSelectNode(NULL)
{
	m_pRootNode = pNode;
	m_ptOrigin = { 0, 0 };
	FormatTree();
}

CBinTree::CBinTree(const CBinTree& src) : m_pSelectNode(NULL)
{
	m_ptOrigin = src.m_ptOrigin;
	m_pRootNode = CNode::dynamicCopyNode(*src.m_pRootNode);
	FormatTree();
}

// create a tree with node of type strType as root
CNode* CBinTree::CreateTree(POINT pt, COLORREF crColor, int iFontSize)
{
	m_ptOrigin = pt;
	m_pRootNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	FormatTree();
	m_pSelectNode = m_pRootNode;
	return m_pRootNode;
}

CNode* CBinTree::CreateNode(LPCTSTR strNodeType, int iCharPos, LONG lfParam, LONG lsParam)
{
	CNode* pNode = NULL;
	if (!_tcscmp(strNodeType, NT_SIGN) ||
		!_tcscmp(strNodeType, NT_GREEKALPHABET) ||
		!_tcscmp(strNodeType, NT_ALPHABET) ||
		!_tcscmp(strNodeType, NT_HANDWRITING) ||
		!_tcscmp(strNodeType, NT_COPPERPLATE) ||
		!_tcscmp(strNodeType, NT_PLUS) ||
		!_tcscmp(strNodeType, NT_MINUS) ||
		!_tcscmp(strNodeType, NT_MULTIPLY) ||
		!_tcscmp(strNodeType, NT_DIVIDE) ||
		!_tcscmp(strNodeType, NT_EQUATION) ||
		!_tcscmp(strNodeType, NT_HYPHEN) ||
		!_tcscmp(strNodeType, NT_DOT) ||
		!_tcscmp(strNodeType, NT_LESSTHANOREQUAL) ||
		!_tcscmp(strNodeType, NT_GREATERTHANOREQUAL) ||
		!_tcscmp(strNodeType, NT_EQUAL) ||
		!_tcscmp(strNodeType, NT_LESSTHAN) ||
		!_tcscmp(strNodeType, NT_GREATERTHAN) ||
		!_tcscmp(strNodeType, NT_NOTEQUAL) ||
		!_tcscmp(strNodeType, NT_PERCENT) ||
		!_tcscmp(strNodeType, NT_SLASH) ||
		!_tcscmp(strNodeType, NT_BACKSLASH) ||
		!_tcscmp(strNodeType, NT_SINGLEQUOTE) ||
		!_tcscmp(strNodeType, NT_COLON) ||
		!_tcscmp(strNodeType, NT_DOUBLEQUOTE) ||
		!_tcscmp(strNodeType, NT_AND) ||
		!_tcscmp(strNodeType, NT_STAR) ||
		!_tcscmp(strNodeType, NT_HASHKEY) ||
		!_tcscmp(strNodeType, NT_QUESTIONMARK) ||
		!_tcscmp(strNodeType, NT_SEMICOLON) ||
		!_tcscmp(strNodeType, NT_VERTICALBAR) ||
		!_tcscmp(strNodeType, NT_EXCLAMATIONMARK) ||
		!_tcscmp(strNodeType, NT_LEFTPARENTHESIS) ||
		!_tcscmp(strNodeType, NT_RIGHTPARENTHESIS) ||
		!_tcscmp(strNodeType, NT_LEFTBRACKET) ||
		!_tcscmp(strNodeType, NT_RIGHTBRACKET) ||
		!_tcscmp(strNodeType, NT_LEFTBRACE) ||
		!_tcscmp(strNodeType, NT_RIGHTBRACE) ||
		!_tcscmp(strNodeType, NT_TILDE) ||
		!_tcscmp(strNodeType, NT_PERIOD) ||
		!_tcscmp(strNodeType, NT_ISEQUIVALENTTO) ||
		!_tcscmp(strNodeType, NT_PLUSORMINUS) ||
		!_tcscmp(strNodeType, NT_COMMA) ||
		!_tcscmp(strNodeType, NT_ISAPPROXIMATELYEQUALTO) ||
		!_tcscmp(strNodeType, NT_INFINITY) ||
		!_tcscmp(strNodeType, NT_SINGLERIGHTARROW) ||
		!_tcscmp(strNodeType, NT_SINCE) ||
		!_tcscmp(strNodeType, NT_HENCE) ||
		!_tcscmp(strNodeType, NT_BELONGTO) ||
		!_tcscmp(strNodeType, NT_CONTAIN) ||
		!_tcscmp(strNodeType, NT_INCLUSION) ||
		!_tcscmp(strNodeType, NT_UNIONOF) ||
		!_tcscmp(strNodeType, NT_INTERSECTIONOF) ||
		!_tcscmp(strNodeType, NT_DELTA) ||
		!_tcscmp(strNodeType, NT_NABLA) ||
		!_tcscmp(strNodeType, NT_VARIESAS) ||
		!_tcscmp(strNodeType, NT_PROPOSITIONALNEGATION) ||
		!_tcscmp(strNodeType, NT_UNIVERSALQUANTIFIER) ||
		!_tcscmp(strNodeType, NT_DOUBLERIGHTARROW) ||
		!_tcscmp(strNodeType, NT_EXISTENTIALQUANTIFIER) ||
		!_tcscmp(strNodeType, NT_PLANCKCONSTANT) ||
		!_tcscmp(strNodeType, NT_LIM) ||
		!_tcscmp(strNodeType, NT_MIN) ||
		!_tcscmp(strNodeType, NT_MAX) ||
		!_tcscmp(strNodeType, NT_LOG) ||
		!_tcscmp(strNodeType, NT_LN) ||
		!_tcscmp(strNodeType, NT_LG) ||
		!_tcscmp(strNodeType, NT_NOTIN) ||
		!_tcscmp(strNodeType, NT_NSUBSETEQ) ||
		!_tcscmp(strNodeType, NT_EMPTYSET) ||
		!_tcscmp(strNodeType, NT_LEFTRIGHTARROW) ||
		!_tcscmp(strNodeType, NT_MAPSTO) ||
		!_tcscmp(strNodeType, NT_epsilon) ||
		!_tcscmp(strNodeType, NT_ALEPH) ||
		!_tcscmp(strNodeType, NT_varrho) ||
		!_tcscmp(strNodeType, NT_BOXMINUS) ||
		!_tcscmp(strNodeType, NT_BOXTIMES) ||
		!_tcscmp(strNodeType, NT_BOXDOT) ||
		!_tcscmp(strNodeType, NT_BOXPLUS) ||
		!_tcscmp(strNodeType, NT_OMINUS) ||
		!_tcscmp(strNodeType, NT_CIRCLEDDASH) ||
		!_tcscmp(strNodeType, NT_OPLUS) ||
		!_tcscmp(strNodeType, NT_OTIMES) ||
		!_tcscmp(strNodeType, NT_OSLASH) ||
		!_tcscmp(strNodeType, NT_ODOT) ||
		!_tcscmp(strNodeType, NT_CIRCLEDCIRC) ||
		!_tcscmp(strNodeType, NT_CIRCLEDAST) ||
		!_tcscmp(strNodeType, NT_BIGODOT) ||
		!_tcscmp(strNodeType, NT_BIGOTIMES) ||
		!_tcscmp(strNodeType, NT_BIGOPLUS) ||
		!_tcscmp(strNodeType, NT_INTEGRAL) ||
		!_tcscmp(strNodeType, NT_DOUBLEINTEGRAL) ||
		!_tcscmp(strNodeType, NT_TRIPLEINTEGRAL) ||
		!_tcscmp(strNodeType, NT_LOOPINTEGRAL) ||
		!_tcscmp(strNodeType, NT_DOUBLELOOPINTEGRAL) ||
		!_tcscmp(strNodeType, NT_TRIPLELOOPINTEGRAL) ||
		!_tcscmp(strNodeType, NT_SUM) ||
		!_tcscmp(strNodeType, NT_SUPREMUM) ||
		!_tcscmp(strNodeType, NT_INFIMUM) ||
		!_tcscmp(strNodeType, NT_PRODUCT) ||
		!_tcscmp(strNodeType, NT_ACCESSORYPRODUCT) ||
		!_tcscmp(strNodeType, NT_UNION) ||
		!_tcscmp(strNodeType, NT_INTERSECTION) ||
		!_tcscmp(strNodeType, NT_SIN) ||
		!_tcscmp(strNodeType, NT_COS) ||
		!_tcscmp(strNodeType, NT_TAN) ||
		!_tcscmp(strNodeType, NT_CSC) ||
		!_tcscmp(strNodeType, NT_SEC) ||
		!_tcscmp(strNodeType, NT_COT) ||
		!_tcscmp(strNodeType, NT_ARCSIN) ||
		!_tcscmp(strNodeType, NT_ARCCOS) ||
		!_tcscmp(strNodeType, NT_ARCTAN) ||
		!_tcscmp(strNodeType, NT_SINH) ||
		!_tcscmp(strNodeType, NT_COSH) ||
		!_tcscmp(strNodeType, NT_TANH) ||
		!_tcscmp(strNodeType, NT_COTH) ||
		!_tcscmp(strNodeType, NT_ARG) ||
		!_tcscmp(strNodeType, NT_DEG) ||
		!_tcscmp(strNodeType, NT_DET) ||
		!_tcscmp(strNodeType, NT_DIM) ||
		!_tcscmp(strNodeType, NT_EXP) ||
		!_tcscmp(strNodeType, NT_GCD) ||
		!_tcscmp(strNodeType, NT_HOM) ||
		!_tcscmp(strNodeType, NT_KER) ||
		!_tcscmp(strNodeType, NT_PR) ||
		!_tcscmp(strNodeType, NT_LIMINF) ||
		!_tcscmp(strNodeType, NT_LIMSUP))
		pNode = CreateOperatorNode(strNodeType, iCharPos, lfParam);
	else if (!_tcscmp(strNodeType, NT_LIMIT) || !_tcscmp(strNodeType, NT_MINIMUM) || !_tcscmp(strNodeType, NT_MAXIMUM))
		pNode = CreateLimitedNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_LOGARITHM))
		pNode = CreateLogarithmNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_SUPERSCRIPT))
		pNode = CreateSuperscriptNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_SUBSCRIPT))
		pNode = CreateSubscriptNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_MIDTOPBOTTOM))
		pNode = CreateMidTopBottomLayoutNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_TOPBOTTOMMID))
		pNode = CreateTopBottomMidLayoutNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_RADICAL))
		pNode = CreateRadicalNode(strNodeType, iCharPos, lfParam);
	else if (!_tcscmp(strNodeType, NT_PARENTHESES) || !_tcscmp(strNodeType, NT_BRACKETS) || !_tcscmp(strNodeType, NT_BRACES) || !_tcscmp(strNodeType, NT_ABSOLUTE))
		pNode = CreateBracketsNode(strNodeType, iCharPos, LOWORD(lfParam), HIWORD(lfParam));
	else if (!_tcscmp(strNodeType, NT_SEPARATOR))
		pNode = CreateSeparatorNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_INTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_INTEGRALTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_DOUBLEINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_DOUBLEINTEGRALTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_TRIPLEINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_TRIPLEINTEGRALTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_LOOPINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_LOOPINTEGRALTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_DOUBLELOOPINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_DOUBLELOOPINTEGRALTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_TRIPLELOOPINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_TRIPLELOOPINTEGRALTBSCRIPT))
		pNode = CreateIntegralNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_SUMTBLIMIT) || !_tcscmp(strNodeType, NT_SUMTBSCRIPT) || !_tcscmp(strNodeType, NT_SUMBLIMIT) || !_tcscmp(strNodeType, NT_SUMBSCRIPT) ||
		!_tcscmp(strNodeType, NT_SUPREMUMTBLIMIT) || !_tcscmp(strNodeType, NT_SUPREMUMTBSCRIPT) || !_tcscmp(strNodeType, NT_SUPREMUMBLIMIT) || !_tcscmp(strNodeType, NT_SUPREMUMBSCRIPT) ||
		!_tcscmp(strNodeType, NT_INFIMUMTBLIMIT) || !_tcscmp(strNodeType, NT_INFIMUMTBSCRIPT) || !_tcscmp(strNodeType, NT_INFIMUMBLIMIT) || !_tcscmp(strNodeType, NT_INFIMUMBSCRIPT) ||
		!_tcscmp(strNodeType, NT_PRODUCTTBLIMIT) || !_tcscmp(strNodeType, NT_PRODUCTTBSCRIPT) || !_tcscmp(strNodeType, NT_PRODUCTBLIMIT) || !_tcscmp(strNodeType, NT_PRODUCTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_ACCESSORYPRODUCTTBLIMIT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTTBSCRIPT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTBLIMIT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_UNIONTBLIMIT) || !_tcscmp(strNodeType, NT_UNIONTBSCRIPT) || !_tcscmp(strNodeType, NT_UNIONBLIMIT) || !_tcscmp(strNodeType, NT_UNIONBSCRIPT) ||
		!_tcscmp(strNodeType, NT_INTERSECTIONTBLIMIT) || !_tcscmp(strNodeType, NT_INTERSECTIONTBSCRIPT) || !_tcscmp(strNodeType, NT_INTERSECTIONBLIMIT) || !_tcscmp(strNodeType, NT_INTERSECTIONBSCRIPT))
		pNode = CreateSumNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_LINE))
		pNode = CreateLineNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_FRACTION))
		pNode = CreateFractionalNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_MATRIX))
		pNode = CreateMatrixNode(strNodeType, iCharPos, LOWORD(lfParam), HIWORD(lfParam));
	else if (!_tcscmp(strNodeType, NT_RIGHTSINGLEARROW) || !_tcscmp(strNodeType, NT_LEFTSINGLEARROW) || !_tcscmp(strNodeType, NT_TWOWAYSINGLEARROW) ||
		!_tcscmp(strNodeType, NT_RIGHTHALFARROW) || !_tcscmp(strNodeType, NT_LEFTHALFARROW) || !_tcscmp(strNodeType, NT_TWOWAYHALFARROW) ||
		!_tcscmp(strNodeType, NT_RIGHTDOUBLEARROW) || !_tcscmp(strNodeType, NT_LEFTDOUBLEARROW) || !_tcscmp(strNodeType, NT_TWOWAYDOUBLEARROW))
		pNode = CreateArrowNode(strNodeType, iCharPos, LOWORD(lfParam), HIWORD(lfParam));
	else if (!_tcscmp(strNodeType, NT_TOPRIGHTSINGLEARROW) ||
		!_tcscmp(strNodeType, NT_TOPLEFTSINGLEARROW) ||
		!_tcscmp(strNodeType, NT_TOPRIGHTHALFARROW) ||
		!_tcscmp(strNodeType, NT_TOPLEFTHALFARROW) ||
		!_tcscmp(strNodeType, NT_TOPTWOWAYSINGLEARROW) ||
		!_tcscmp(strNodeType, NT_TOPONEPOINT) ||
		!_tcscmp(strNodeType, NT_TOPTWOPOINT) ||
		!_tcscmp(strNodeType, NT_TOPTHREEPOINT) ||
		!_tcscmp(strNodeType, NT_TOPONELINE) ||
		!_tcscmp(strNodeType, NT_TOPTWOLINE) ||
		!_tcscmp(strNodeType, NT_TOPACUTEACCENT) ||
		!_tcscmp(strNodeType, NT_TOPGRAVEACCENT) ||
		!_tcscmp(strNodeType, NT_TOPCIRCUMFLEXACCENT) ||
		!_tcscmp(strNodeType, NT_TOPMODULATEACCENT) ||
		!_tcscmp(strNodeType, NT_TOPTILDE) ||
		!_tcscmp(strNodeType, NT_TOPBREVEACCENT))
		pNode = CreateTaggedSignNode(strNodeType, iCharPos);
	else if (!_tcscmp(strNodeType, NT_INVERSE))
		pNode = CreateInverseNode(strNodeType, iCharPos, lfParam);
	
	FormatTree();
	
	return pNode;
}

CNode* CBinTree::CreateOperatorNode(LPCTSTR strNodeType, int iCharPos, LONG lfParam)
{
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();
	//拆分字符串
	TCHAR strText[MAX_PATH], strLeftText[MAX_PATH], strRightText[MAX_PATH];
	::ZeroMemory(&strText, sizeof(strText));
	::ZeroMemory(&strLeftText, sizeof(strLeftText));
	::ZeroMemory(&strRightText, sizeof(strRightText));
	lstrcpy(strText, m_pSelectNode->GetText());
	lstrcpyn(strLeftText, strText, iCharPos + 1);
	lstrcpy(strRightText, strText + iCharPos);

	CNode* pNode = new COperatorNode(strNodeType, lfParam == 0 ? GetOperatorTextByNodeType(strNodeType) : (LPCTSTR)lfParam, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, strLeftText, crColor, iFontSize);
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, strRightText, crColor, iFontSize);
	
	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateInplacedNode(LPCTSTR strNodeType, int iCharPos)
{
	CNode* pInplaceNode1 = CreateOperatorNode(NT_INPLACE, iCharPos);
	m_pSelectNode = pInplaceNode1->m_pLeftChild;
	CNode* pInplaceNode2 = CreateOperatorNode(NT_INPLACE, iCharPos);
	m_pSelectNode = pInplaceNode2->m_pRightChild;
	return pInplaceNode2;
}

CNode* CBinTree::CreateLimitedNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CLimitedNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);

	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);
	
	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateLogarithmNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CLogarithmNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateSuperscriptNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CSuperscriptNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
	
	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pLeftChild;

	return pNode;
}

CNode* CBinTree::CreateSubscriptNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CSubscriptNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
	
	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pLeftChild;

	return pNode;
}

CNode* CBinTree::CreateMidTopBottomLayoutNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CMidTopBottomLayoutNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);

	//创建右孩子
	CNode* rpNode = new CTopBottomNode(NT_TOPBOTTOM, crColor, iFontSize / 2);

	//创建左孩子
	CNode* rlpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);

	//创建右孩子
	CNode* rrpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);

	rpNode->SetLeftChild(rlpNode);
	rpNode->SetRightChild(rrpNode);

	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = rpNode->m_pLeftChild;

	return pNode;
}

CNode* CBinTree::CreateTopBottomMidLayoutNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CTopBottomMidLayoutNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CTopBottomNode(NT_TOPBOTTOM, crColor, iFontSize / 2);

	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);

	//创建左孩子
	CNode* llpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);

	//创建右孩子
	CNode* lrpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);

	lpNode->SetLeftChild(llpNode);
	lpNode->SetRightChild(lrpNode);

	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = rpNode;

	return pNode;
}

CNode* CBinTree::CreateRadicalNode(LPCTSTR strNodeType, int iCharPos, bool bLeftChild)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CRadicalNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	if (bLeftChild) {
		CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
		pNode->SetLeftChild(lpNode);
	}
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateBracketsNode(LPCTSTR strNodeType, int iCharPos, bool bLeftPart, bool bRightPart)
{
	if (!bLeftPart && !bRightPart)
		return NULL;

	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CBracketsNode(strNodeType, crColor, iFontSize, bLeftPart, bRightPart);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	//括号节点没有右孩子

	pNode->SetLeftChild(lpNode);
	
	m_pSelectNode = pNode->m_pLeftChild;

	return pNode;
}

CNode* CBinTree::CreateSeparatorNode(LPCTSTR strNodeType, int iCharPos)
{
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();
	//拆分字符串
	TCHAR strText[MAX_PATH], strLeftText[MAX_PATH], strRightText[MAX_PATH];
	::ZeroMemory(&strText, sizeof(strText));
	::ZeroMemory(&strLeftText, sizeof(strLeftText));
	::ZeroMemory(&strRightText, sizeof(strRightText));
	lstrcpy(strText, m_pSelectNode->GetText());
	lstrcpyn(strLeftText, strText, iCharPos + 1);
	lstrcpy(strRightText, strText + iCharPos);

	CNode* pNode = new CSeparatorNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, strLeftText, crColor, iFontSize);

	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, strRightText, crColor, iFontSize);

	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateIntegralNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = NULL;
	if (!_tcscmp(strNodeType, NT_INTEGRALTBSCRIPT) || !_tcscmp(strNodeType, NT_DOUBLEINTEGRALTBSCRIPT) || !_tcscmp(strNodeType, NT_TRIPLEINTEGRALTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_LOOPINTEGRALTBSCRIPT) || !_tcscmp(strNodeType, NT_DOUBLELOOPINTEGRALTBSCRIPT) || !_tcscmp(strNodeType, NT_TRIPLELOOPINTEGRALTBSCRIPT))
		pNode = new CMidTopBottomLargeOperatorNode(strNodeType, crColor, iFontSize);
	else if (!_tcscmp(strNodeType, NT_INTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_DOUBLEINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_TRIPLEINTEGRALTBLIMIT) ||
		!_tcscmp(strNodeType, NT_LOOPINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_DOUBLELOOPINTEGRALTBLIMIT) || !_tcscmp(strNodeType, NT_TRIPLELOOPINTEGRALTBLIMIT))
		pNode = new CTopMidBottomLargeOperatorNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);

	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);

	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateSumNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = NULL;
	if (!_tcscmp(strNodeType, NT_SUMTBLIMIT) || !_tcscmp(strNodeType, NT_SUPREMUMTBLIMIT) || !_tcscmp(strNodeType, NT_INFIMUMTBLIMIT) ||
		!_tcscmp(strNodeType, NT_PRODUCTTBLIMIT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTTBLIMIT) || !_tcscmp(strNodeType, NT_UNIONTBLIMIT) || !_tcscmp(strNodeType, NT_INTERSECTIONTBLIMIT))
		pNode = new CTopMidBottomLargeOperatorNode(strNodeType, crColor, iFontSize);
	else if (!_tcscmp(strNodeType, NT_SUMTBSCRIPT) || !_tcscmp(strNodeType, NT_SUPREMUMTBSCRIPT) || !_tcscmp(strNodeType, NT_INFIMUMTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_PRODUCTTBSCRIPT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTTBSCRIPT) || !_tcscmp(strNodeType, NT_UNIONTBSCRIPT) || !_tcscmp(strNodeType, NT_INTERSECTIONTBSCRIPT))
		pNode = new CMidTopBottomLargeOperatorNode(strNodeType, crColor, iFontSize);
	else if (!_tcscmp(strNodeType, NT_SUMBLIMIT) || !_tcscmp(strNodeType, NT_SUPREMUMBLIMIT) || !_tcscmp(strNodeType, NT_INFIMUMBLIMIT) ||
		!_tcscmp(strNodeType, NT_PRODUCTBLIMIT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTBLIMIT) || !_tcscmp(strNodeType, NT_UNIONBLIMIT) || !_tcscmp(strNodeType, NT_INTERSECTIONBLIMIT))
		pNode = new CMidBottomLargeOperatorNode(strNodeType, crColor, iFontSize);
	else if (!_tcscmp(strNodeType, NT_SUMBSCRIPT) || !_tcscmp(strNodeType, NT_SUPREMUMBSCRIPT) || !_tcscmp(strNodeType, NT_INFIMUMBSCRIPT) ||
		!_tcscmp(strNodeType, NT_PRODUCTBSCRIPT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTBSCRIPT) || !_tcscmp(strNodeType, NT_UNIONBSCRIPT) || !_tcscmp(strNodeType, NT_INTERSECTIONBSCRIPT))
		pNode = new CMidRightBottomLargeOperatorNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	if (!_tcscmp(strNodeType, NT_SUMTBLIMIT) || !_tcscmp(strNodeType, NT_SUMTBSCRIPT) || !_tcscmp(strNodeType, NT_SUPREMUMTBLIMIT) || !_tcscmp(strNodeType, NT_SUPREMUMTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_INFIMUMTBLIMIT) || !_tcscmp(strNodeType, NT_INFIMUMTBSCRIPT) || !_tcscmp(strNodeType, NT_PRODUCTTBLIMIT) || !_tcscmp(strNodeType, NT_PRODUCTTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_ACCESSORYPRODUCTTBLIMIT) || !_tcscmp(strNodeType, NT_ACCESSORYPRODUCTTBSCRIPT) || !_tcscmp(strNodeType, NT_UNIONTBLIMIT) || !_tcscmp(strNodeType, NT_UNIONTBSCRIPT) ||
		!_tcscmp(strNodeType, NT_INTERSECTIONTBLIMIT) || !_tcscmp(strNodeType, NT_INTERSECTIONTBSCRIPT)) {
		//创建左孩子
		CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
		pNode->SetLeftChild(lpNode);
	}

	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize / 2);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

/*
行节点的增删规则
1.分式幂式等特殊节点不能增加行。
2.只能删除空行。
*/
CNode* CBinTree::CreateLineNode(LPCTSTR strNodeType, int iCharPos)
{
	CNode* pCurNode = m_pSelectNode;
	while (pCurNode) {
		if (!pCurNode->m_pParent || !_tcscmp(pCurNode->m_pParent->GetNodeType(), NT_LINE))
			break;
		CNode* pParent = pCurNode->m_pParent;
		if (!pParent->GetDelMode()) {
			return NULL;
		}
		pCurNode = pCurNode->m_pParent;
	}
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();
	//拆分字符串
	TCHAR strText[MAX_PATH], strLeftText[MAX_PATH], strRightText[MAX_PATH];
	::ZeroMemory(&strText, sizeof(strText));
	::ZeroMemory(&strLeftText, sizeof(strLeftText));
	::ZeroMemory(&strRightText, sizeof(strRightText));
	lstrcpy(strText, m_pSelectNode->GetText());
	lstrcpyn(strLeftText, strText, iCharPos + 1);
	lstrcpy(strRightText, strText + iCharPos);

	CNode* pEdit = new CEditNode(NT_STANDARD, strLeftText, crColor, iFontSize);
	m_pSelectNode->SetText(strRightText);
	CNode* pLine1 = pEdit;
	CNode* pLine2 = m_pSelectNode;
	pCurNode = m_pSelectNode;
	while (pCurNode) {
		if (!pCurNode->m_pParent || !_tcscmp(pCurNode->m_pParent->GetNodeType(), NT_LINE))
			break;
		CNode* pParent = pCurNode->m_pParent;
		if (pCurNode == pParent->m_pLeftChild) {
			pParent->SetLeftChild(pLine2);
			pLine2 = pParent;
		}
		else if (pCurNode == pParent->m_pRightChild) {
			pParent->SetRightChild(pLine1);
			pLine1 = pParent;
		}
		pCurNode = pCurNode->m_pParent;
	}

	CNode* pNode = new CLineNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(pCurNode, pNode);
	
	pNode->SetLeftChild(pLine1);
	pNode->SetRightChild(pLine2);

	return pNode;
}

CNode* CBinTree::CreateFractionalNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CFractionalNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	//创建右孩子
	CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	pNode->SetLeftChild(lpNode);
	pNode->SetRightChild(rpNode);

	m_pSelectNode = pNode->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateMatrixNode(LPCTSTR strNodeType, int iCharPos, LONG lfParam, LONG lsParam)
{
	//if (m_pSelectNode->GetMatrixRootNode())//不支持矩阵中嵌套矩阵
	//	return NULL;

	int iRow = lfParam, iColumn = lsParam;

	assert(iRow > 0 && iColumn > 0);
	assert(!(iRow == 1 && iColumn == 1));

	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pMatrixNode = NULL;

	for (int i = 0; i < iRow; ++i) {
		CNode* vpNode = NULL;
		if (i < iRow - 1) {
			vpNode = new CVerticalMatrix(NT_VERTICALMATRIX, crColor, iFontSize);

			if (iRow > 1 && i == 0)
				pMatrixNode = vpNode;

			//替换节点
			ReplaceNode(m_pSelectNode, vpNode);
			delete m_pSelectNode;
		}

		//建立水平上的节点
		if (i < iRow - 1)
			m_pSelectNode = vpNode->m_pRightChild;

		for (int j = 0; j < iColumn - 1; ++j) {
			CNode* hpNode = new CHorizontalMatrix(NT_HORIZONTALMATRIX, crColor, iFontSize);

			if (iRow == 1 && iColumn > 1 && j == 0)
				pMatrixNode = hpNode;

			//替换节点
			ReplaceNode(m_pSelectNode, hpNode);
			delete m_pSelectNode;
			m_pSelectNode = hpNode->m_pLeftChild;
		}

		if (!vpNode)
			break;
		m_pSelectNode = vpNode->m_pLeftChild;
	}

	return pMatrixNode;
}

CNode* CBinTree::CreateArrowNode(LPCTSTR strNodeType, int iCharPos, bool bLeftChild, bool bRightChild)
{
	if (!bLeftChild && !bRightChild)
		return NULL;

	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CArrowNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	if (bLeftChild) {
		CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
		pNode->SetLeftChild(lpNode);
		m_pSelectNode = pNode->m_pLeftChild;
	}
	
	//创建右孩子
	if (bRightChild) {
		CNode* rpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
		pNode->SetRightChild(rpNode);
		m_pSelectNode = pNode->m_pRightChild;
	}

	return pNode;
}

CNode* CBinTree::CreateTaggedSignNode(LPCTSTR strNodeType, int iCharPos)
{
	CreateInplacedNode(NT_INPLACE, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	CNode* pNode = new CTaggedSignNode(strNodeType, crColor, iFontSize);

	//替换节点
	ReplaceNode(m_pSelectNode, pNode);
	delete m_pSelectNode;
	m_pSelectNode = pNode;

	//创建左孩子
	CNode* lpNode = new CEditNode(NT_STANDARD, _T(""), crColor, iFontSize);
	
	//标记符号节点没有右孩子

	pNode->SetLeftChild(lpNode);
	
	m_pSelectNode = pNode->m_pLeftChild;

	return pNode;
}

CNode* CBinTree::CreateInverseNode(LPCTSTR strNodeType, int iCharPos, LONG lfParam)
{
	CNode* pNode = CreateSuperscriptNode(NT_SUPERSCRIPT, iCharPos);
	pNode->m_pRightChild->SetText(_T("-1"));
	m_pSelectNode = pNode->m_pLeftChild;
	CNode* lpNode = CreateOperatorNode((LPCTSTR)lfParam, iCharPos);
	COLORREF crColor = m_pSelectNode->GetColor();
	int iFontSize = m_pSelectNode->GetFontSize();

	m_pSelectNode = pNode->m_pParent->m_pParent->m_pRightChild;

	return pNode;
}

CNode* CBinTree::CreateFormulaTree(LPCTSTR strFormulaText, int iCharPos)
{
	if (_tcslen(strFormulaText) && _tcsstr(strFormulaText, _T("formula"))) {
		const TCHAR* strtok1 = _tcschr(strFormulaText, _T('{'));
		const TCHAR* strtok2 = _tcsrchr(strFormulaText, _T('}'));
		int iLength = _tcslen(strtok1) - _tcslen(strtok2) - 1;
		TCHAR* strText = new TCHAR[iLength + 1];
		_tcsncpy(strText, strtok1 + 1, iLength);
		strText[iLength] = 0;
		CNode* pRootNode = CNode::load(strText);
		delete[] strText;

		if (pRootNode) {
			//拆分字符串
			TCHAR strText[MAX_PATH], strLeftText[MAX_PATH], strRightText[MAX_PATH];
			::ZeroMemory(&strText, sizeof(strText));
			::ZeroMemory(&strLeftText, sizeof(strLeftText));
			::ZeroMemory(&strRightText, sizeof(strRightText));
			_tcscpy(strText, m_pSelectNode->GetText());
			_tcsncpy(strLeftText, strText, iCharPos + 1);
			CNode* pFarLeftNode = m_pRootNode->GetLeftEditNode(pRootNode);
			_tcscat(strLeftText, pFarLeftNode->GetText());
			pFarLeftNode->SetText(strLeftText);
			CNode* pFarRightNode = m_pRootNode->GetRightEditNode(pRootNode);
			_tcscpy(strRightText, pFarRightNode->GetText());
			_tcscat(strRightText, strText + iCharPos);
			pFarRightNode->SetText(strRightText);

			COLORREF crColor = m_pSelectNode->GetColor();
			int iFontSize = m_pSelectNode->GetFontSize();
			pRootNode->ChangeFontSize(iFontSize);
			pRootNode->ChangeColor(crColor);

			//替换节点
			ReplaceNode(m_pSelectNode, pRootNode);
			delete m_pSelectNode;
			m_pSelectNode = pRootNode->GetRightEditNode(pRootNode);

			FormatTree();
			return pRootNode;
		}
	}
	return NULL;
}

LRESULT CBinTree::DelSelectNode()
{
	LRESULT lRes = 0;
	if (m_pSelectNode && m_pSelectNode->m_pParent) {
		CNode* pFather = m_pSelectNode->m_pParent;
		CNode* pDel = NULL;
		CNode* pJoin = NULL;
		TCHAR strText[MAX_PATH];
		::ZeroMemory(&strText, sizeof(strText));
		if (!pFather->GetDelMode()) {
			//这些节点都需要占位节点来连接其他节点，在子节点处不能删除任何节点。
		}
		else if (pDel = m_pSelectNode->GetDelNode()) {
			pDel = pDel->m_pParent;
			if (pDel && !_tcscmp(pDel->GetNodeType(), NT_INPLACE)) {
				ReplaceNode(pDel, pDel->m_pLeftChild);
				pDel->m_pLeftChild = NULL;
				lRes = 2;//此处返回2表示还需要调用一次来删除一个占位节点
				delete pDel;
				pDel = NULL;
				FormatTree();
			}
		}
		else if (!_tcscmp(pFather->GetNodeType(), NT_LINE)) {//行节点需要特殊考虑
			if (!lstrlen(m_pSelectNode->GetText())) {//删除当前空行
				pDel = pFather;
				if (m_pSelectNode->IsLeftChild()) {
					m_pSelectNode = pFather->m_pRightChild->GetLeftEditNode(pFather->m_pRightChild, false);
					ReplaceNode(pFather, pFather->m_pRightChild);
					pFather->m_pRightChild = NULL;
				}
				else if (m_pSelectNode->IsRightChild()) {
					m_pSelectNode = pFather->m_pLeftChild->GetRightEditNode(pFather->m_pLeftChild, false);
					ReplaceNode(pFather, pFather->m_pLeftChild);
					pFather->m_pLeftChild = NULL;
				}
			}
		}
		else {
			pJoin = m_pSelectNode->GetLeftJointNode();
			pDel = GetAncestorNode(m_pSelectNode, pJoin);
			if (!pDel || pJoin == m_pSelectNode)
				return 0;

			if (m_pSelectNode->m_pParent == pDel && pJoin->m_pParent == pDel) {
				lstrcpy(strText, pJoin->GetText());
				lstrcat(strText, m_pSelectNode->GetText());
				m_pSelectNode->SetText(strText);
				ReplaceNode(pFather, m_pSelectNode);
				pFather->m_pRightChild = NULL;
			}
			else if (m_pSelectNode->m_pParent == pDel) {
				lstrcpy(strText, pJoin->GetText());
				lstrcat(strText, m_pSelectNode->GetText());
				pJoin->SetText(strText);
				m_pSelectNode = pJoin;
				ReplaceNode(pDel, pDel->m_pLeftChild);
				pDel->m_pLeftChild = NULL;
			}
			else if (pJoin->m_pParent == pDel) {
				lstrcpy(strText, pJoin->GetText());
				lstrcat(strText, m_pSelectNode->GetText());
				m_pSelectNode->SetText(strText);
				ReplaceNode(pDel, pDel->m_pRightChild);
				pDel->m_pRightChild = NULL;
			}
			else {
				lstrcpy(strText, pJoin->GetText());
				lstrcat(strText, m_pSelectNode->GetText());
				m_pSelectNode->SetText(strText);

				ReplaceNode(pJoin, pDel->m_pRightChild);
				pDel->m_pRightChild = NULL;
				delete pJoin;
				ReplaceNode(pDel, pDel->m_pLeftChild);
				pDel->m_pLeftChild = NULL;
			}
		}
		if (pDel) {
			delete pDel;
			FormatTree();
			lRes = 1;
		}
	}
	return lRes;
}

bool CBinTree::DelNode(UINT iDelMode)
{
	bool lRet = false;
	if (iDelMode != VK_BACK && iDelMode != VK_DELETE)
		return lRet;

	CNode* pNode = m_pSelectNode;
	if (iDelMode == VK_DELETE) {
		m_pSelectNode = m_pSelectNode->GetRightJointNode();
	}
	LRESULT lRes = DelSelectNode();
	if (lRes) {
		lRet = true;
		if (lRes == 2)
			DelSelectNode();
	}
	else
		m_pSelectNode = pNode;

	return lRet;
}

void CBinTree::FormatTree()
{
	m_pRootNode->UpdateRect();
	int offsetX = m_ptOrigin.x - m_pRootNode->GetRect().left;
	int offsetY = m_ptOrigin.y - m_pRootNode->GetRect().top;
	m_pRootNode->TranslateRect(offsetX, offsetY);
}

void CBinTree::ReplaceNode(CNode* pDestNode, CNode* pSrcNode)
{
	if (pDestNode != m_pRootNode) {
		CNode* pParent = pDestNode->GetParentNode();

		if (pParent->GetLeftChild() == pDestNode)
			pParent->SetLeftChild(pSrcNode);
		else if (pParent->GetRightChild() == pDestNode)
			pParent->SetRightChild(pSrcNode);

		pSrcNode->m_pParent = pParent;
	}
	else {
		//delete m_pRootNode;
		m_pRootNode = pSrcNode;
		pSrcNode->m_pParent = NULL;

		if (!_tcscmp(pSrcNode->GetNodeType(), NT_STANDARD))
			pSrcNode->SetMinWidth(10);
	}
}

// return the root node of the tree
CNode* CBinTree::GetRootNode()
{
	return m_pRootNode;
}

// sets the root node of the tree
void CBinTree::SetRootNode(CNode* pNode)
{
	m_pRootNode = pNode;
}

// set the selected node
void CBinTree::SetSelectNode(CNode* pNode)
{
	m_pSelectNode = pNode;
}

// return the currently selected node
CNode* CBinTree::GetSelectedNode()
{
	return m_pSelectNode;
}

POINT CBinTree::GetOriginPoint()
{
	return m_ptOrigin;
}

void CBinTree::ChangeFontSize(int iFontSize)
{
	m_pRootNode->ChangeFontSize(iFontSize);
	FormatTree();
}

void CBinTree::ChangeColor(COLORREF crColor)
{
	m_pRootNode->ChangeColor(crColor);
}

void CBinTree::preTraverseDrawTreeNodes(CNode* T, Gdiplus::Graphics* pGraphics)
{
	if (T)
	{
		if (T != m_pSelectNode)//当前选中节点由文本框来显示，当公式编辑器窗口关闭时需要把选中节点指向别处
			T->DrawNode(pGraphics);
		else
			T->DrawNodeRegion(pGraphics);
		preTraverseDrawTreeNodes(T->m_pLeftChild, pGraphics);
		preTraverseDrawTreeNodes(T->m_pRightChild, pGraphics);
	}
}

// draw the tree (inorder)
void CBinTree::DrawTree(Gdiplus::Graphics* pGraphics, bool bShowBorder)
{
	if (m_pRootNode)
		preTraverseDrawTreeNodes(m_pRootNode, pGraphics);
		//m_pRootNode->DrawNode(pDC);

	m_pRootNode->DrawNodeRegion(pGraphics, bShowBorder);
}

HBITMAP CBinTree::GetHBITMAP()
{
	LONG m_lWndWidth = m_pRootNode->GetWidth();
	LONG m_lWndHeight = m_pRootNode->GetHeight();
	HWND hWndDesktop = ::GetDesktopWindow();
	HDC hDcDesktop = GetDC(hWndDesktop);
	ASSERT(hDcDesktop != NULL);

	//创建与windowDC兼容的内存设备环境  
	HDC hDcMem = CreateCompatibleDC(hDcDesktop);
	//位图的初始化和载入位图     
	HBITMAP hBmpMem = CreateCompatibleBitmap(hDcDesktop, m_lWndWidth, m_lWndHeight);
	HBITMAP hBmpOld = (HBITMAP)SelectObject(hDcMem, hBmpMem);

	//画背景颜色
	CRenderEngine::DrawColor(hDcMem, RECT{ 0, 0, m_lWndWidth, m_lWndHeight }, 0xFFFFFFFF);

	//使用GDI+
	//获取这块内存画布的Graphics引用
    Gdiplus::Graphics graphics(hDcMem);

	//设置线为高质量平滑模式
	graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
	graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);//消除文本锯齿，使用网格匹配
	//memGr.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);//消除文本锯齿，不使用网格匹配 

	//画公式
	DrawTree(&graphics);

	//SelectObject(hDcMem, hBmpOld);
	//释放资源
	DeleteDC(hDcMem);
	DeleteObject(hBmpOld);

	::ReleaseDC(hWndDesktop, hDcDesktop);
	return hBmpMem;
}

CNode* CBinTree::GetNodeFromPoint(POINT pt)
{
	CNode* pRet = NULL;
	if (PtInRect(&m_pRootNode->GetRect(), pt))
		pRet = m_pRootNode->GetNodeFromPoint(pt);
	return pRet;
}

RECT CBinTree::UpdateSelectNode(LPCTSTR strText)
{
	m_pSelectNode->SetText(strText);
	FormatTree();
	return m_pSelectNode->GetRect();
}

CNode* CBinTree::GetAncestorNode(CNode* pNode1, CNode* pNode2)
{
	if (!pNode1 || !pNode2)
		return NULL;

	CNode* pAncestor1 = NULL;
	CNode* pAncestor2 = NULL;

	pAncestor1 = pNode1->m_pParent;
	while (pAncestor1) {
		pAncestor2 = pNode2->m_pParent;
		while (pAncestor2 && pAncestor1 != pAncestor2)
			pAncestor2 = pAncestor2->m_pParent;

		if (pAncestor1 == pAncestor2)
			break;
		else
			pAncestor1 = pAncestor1->m_pParent;
	}

	return pAncestor2;
}

int CBinTree::HitTest(POINT point)
{
	TrackerHit hitResult = hitNothing;

	if (PtInRect(&(m_pRootNode->GetRect()), point))
		hitResult = hitMiddle;

	return hitResult;
}

BOOL CBinTree::SetCursor(HWND pWnd, UINT nHitTest)
{
	// trackers should only be in client area
	if (nHitTest != HTCLIENT)
		return FALSE;

	// convert cursor position to client co-ordinates
	POINT point;
	GetCursorPos(&point);
	ScreenToClient(pWnd, &point);

	// do hittest and normalize hit
	int nHandle = HitTest(point);
	if (nHandle < 0)
		return FALSE;

	assert(nHandle < _countof(_afxCursors));
	::SetCursor(_afxCursors[nHandle]);
	return TRUE;
}

BOOL CBinTree::Track(HWND pWnd, POINT point, BOOL bAllowInvert,
	HWND pWndClipTo)
{
	// perform hit testing on the handles
	int nHandle = HitTest(point);
	if (nHandle < 0)
	{
		// didn't hit a handle, so just return FALSE
		return FALSE;
	}

	// otherwise, call helper function to do the tracking
	//m_bAllowInvert = bAllowInvert;

	return TrackHandle(nHandle, pWnd, point, pWndClipTo);
}

void CBinTree::TranslateTree(int iTranslateX, int iTranslateY)
{
	m_ptOrigin.x += iTranslateX;
	m_ptOrigin.y += iTranslateY;
	m_pRootNode->TranslateRect(iTranslateX, iTranslateY);
}

void CBinTree::ModifyPointers(int nHandle, POINT ptOriginSave, POINT ptOriginOld, POINT ptDown, POINT ptLast)
{
	assert(nHandle >= 0);
	assert(nHandle <= 9);

	if (nHandle == hitMiddle) {//移动区域
		int offsetX = ptOriginSave.x + ptLast.x - ptDown.x - ptOriginOld.x;
		int offsetY = ptOriginSave.y + ptLast.y - ptDown.y - ptOriginOld.y;
		TranslateTree(offsetX, offsetY);
	}
}

BOOL CBinTree::TrackHandle(int nHandle, HWND pWnd, POINT point,
	HWND pWndClipTo)
{
	assert(nHandle >= 0);
	assert(nHandle <= 9);

	// don't handle if capture already set
	if (::GetCapture() != NULL)
		return FALSE;

	//AfxLockTempMaps();  // protect maps while looping

	// set capture to the window which received this message
	SetCapture(pWnd);
	assert(pWnd == GetCapture());
	UpdateWindow(pWnd);
	if (pWndClipTo != NULL)
		UpdateWindow(pWndClipTo);
	POINT ptOriginSave;
	ptOriginSave.x = m_ptOrigin.x;
	ptOriginSave.y = m_ptOrigin.y;

	POINT ptOriginOld;
	BOOL bMoved = FALSE;
	POINT ptLast;

	// get messages until capture lost or cancelled/accepted
	for (;;)
	{
		MSG msg;
		assert(::GetMessage(&msg, NULL, 0, 0));

		if (GetCapture() != pWnd)
			break;

		switch (msg.message)
		{
			// handle movement/accept messages
		case WM_LBUTTONUP:

			goto ExitLoop;

			break;
		case WM_MOUSEMOVE:
			ptOriginOld.x = m_ptOrigin.x;
			ptOriginOld.y = m_ptOrigin.y;

			ptLast = { GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam) };
			ModifyPointers(nHandle, ptOriginSave, ptOriginOld, point, ptLast);

			// only redraw and callback if the rect actually changed!
			if (!(ptOriginOld.x == m_ptOrigin.x && ptOriginOld.y == m_ptOrigin.y))
			{
				bMoved = TRUE;
				InvalidateRect(pWnd, NULL, false);
				UpdateWindow(pWnd);
			}

			break;

			// handle cancel messages
		case WM_KEYDOWN:
			if (msg.wParam != VK_ESCAPE)
				break;
		case WM_RBUTTONDOWN:
			if (bMoved)
			{
				InvalidateRect(pWnd, NULL, false);
				UpdateWindow(pWnd);
			}
			goto ExitLoop;

			// just dispatch rest of the messages
		default:
			DispatchMessage(&msg);
			break;
		}
	}

ExitLoop:
	ReleaseCapture();

	//AfxUnlockTempMaps(FALSE);

	// restore rect in case bMoved is still FALSE
	if (!bMoved) {
		m_ptOrigin.x = ptOriginSave.x;
		m_ptOrigin.y = ptOriginSave.y;
	}

	// return TRUE only if rect has changed
	return !(ptOriginSave.x == m_ptOrigin.x && ptOriginSave.y == m_ptOrigin.y);
}

void CBinTree::save()
{
	TCHAR strFormulaText[MAX_FORMULA_TEXT_LENGTH];
	::ZeroMemory(strFormulaText, sizeof(strFormulaText));
	_tcscat(strFormulaText, _T("formula{"));
	m_pRootNode->save(strFormulaText);
	_tcscat(strFormulaText, _T("}"));
	_tcscat(strFormulaText, _T("fontsize:"));
	TCHAR mark[64];
	::ZeroMemory(&mark, sizeof(mark));
	_itot(m_pRootNode->GetFontSize(), mark, 10);
	_tcscat(strFormulaText, mark);
	_tcscat(strFormulaText, _T("color:"));
	::ZeroMemory(&mark, sizeof(mark));
	_ultot(m_pRootNode->GetColor(), mark, 10);
	_tcscat(strFormulaText, mark);
	m_pLog->WriteLog(strFormulaText);
}

CBinTree* CBinTree::load(LPCTSTR strFormulaText)
{
	if (_tcslen(strFormulaText) && _tcsstr(strFormulaText, _T("formula"))) {
		const TCHAR* strtok1 = _tcschr(strFormulaText, _T('{'));
		const TCHAR* strtok2 = _tcsrchr(strFormulaText, _T('}'));
		int iLength = _tcslen(strtok1) - _tcslen(strtok2) - 1;
		TCHAR* strText = new TCHAR[iLength + 1];
		_tcsncpy(strText, strtok1 + 1, iLength);
		strText[iLength] = 0;
		CNode* pRootNode = CNode::load(strText);
		const TCHAR* strtok3 = _tcsstr(strtok2, _T("fontsize:"));
		const TCHAR* strtok4 = _tcsstr(strtok3, _T("color:"));
		TCHAR mark[64];
		::ZeroMemory(&mark, sizeof(mark));
		_tcsncpy(mark, strtok3 + _tcslen(_T("fontsize:")), _tcslen(strtok3) - _tcslen(strtok4) - _tcslen(_T("fontsize:")));
		pRootNode->ChangeFontSize(_ttoi(mark));
		::ZeroMemory(&mark, sizeof(mark));
		_tcsncpy(mark, strtok4 + _tcslen(_T("color:")), _tcslen(strtok4) - _tcslen(_T("color:")));
		pRootNode->ChangeColor(_tcstoul(mark, NULL, 10));
		//TCHAR iFontSize[64] = { 0 };
		//TCHAR color[64] = { 0 };
		//_stscanf(strtok3, _T("fontsize:%[1-9]color:%[1-9]"), iFontSize, color);
		delete[] strText;
		return new CBinTree(pRootNode);
	}
	else
		return NULL;
}
